﻿using Chloe;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace Aierp.Utility.Data
{
    public class DbInstance
    {
        IDbContext _dbContext;
        public IDbContext Db
        {
            get
            {
                if (this._dbContext == null)
                {
                    _dbContext = DbContextFactory.CreateContext();
                }
                return _dbContext;
            }
            set
            {
                this._dbContext = value;
            }
        }

        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <typeparam name="T">需要获取分页的实体</typeparam>
        /// <typeparam name="TKey">object</typeparam>
        /// <param name="limit">页面大小</param>
        /// <param name="offset">偏移量</param>
        /// <param name="where">查询条件表达式，条件可选，为空时写null</param>
        /// <param name="order">排序条件表达式,必填，可写 c=>c.KeyId 主要作用是指出排序字段</param>
        /// <param name="sortOrder">排序类型 默认：asc或 desc</param>
        /// <returns></returns>
        public string GetPageList<T, TKey>(int limit, int offset, Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, string sortOrder = "asc")
          where T : class, new()
        {
            IQuery<T> query = Db.Query<T>();

            var total = (where != null) ? query.Where(where).Count() : query.Count();

            var pageInfo = new PageInfo(total, limit, offset);

            //limit = GetLimit(limit, ref offset, total);

            query = (sortOrder.IsEmpty() || sortOrder == "asc") ? query.OrderBy(order) : query.OrderByDesc(order);

            if (where != null) query = query.Where(where);

            query = query.Skip(pageInfo.Offset).Take(pageInfo.Limit);

            return JSONhelper.GetJsonforBootstrapTable(total, query.ToList());
        }

        /// <summary>
        /// 根据表达式查询对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where">查询表达式</param>
        /// <returns></returns>
        public T FindBy<T>(Expression<Func<T, bool>> where) where T : class, new()
        {
            if (where == null) return null;
            IQuery<T> query = Db.Query<T>();
            var result = query.Where(where).FirstOrDefault();
            return result;
        }

        public List<T> Find<T>() where T : class, new()
        {
            IQuery<T> query = Db.Query<T>();
            return query.Take(1000).ToList();
        }

        /// <summary>
        /// 插入数据到数据库，插入前检查对象是否已经存在
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item"></param>
        /// <param name="where"></param>
        /// <returns></returns>
        public Tuple<int,T> Insert<T>(T item, Expression<Func<T, bool>> where) where T : class, new()
        {
            var result = IsExits<T>(item, where);
            if (result < 0) return new Tuple<int, T>(result,null);

            var ret = Db.Insert<T>(item);

            return new Tuple<int, T>(result, ret);
        }

        public T Insert<T>(T item) where T : class, new()
        {
            var ret = Db.Insert<T>(item);

            return ret;
        }

        /// <summary>
        /// 检查对象是否在数据库中存在
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item">对象</param>
        /// <param name="where">查询条件表达式</param>
        /// <returns>-9 传入的查询实体对象为空；1 实体对象已经存在；0 不存在（正常情况返回1）</returns>
        public int IsExits<T>(T item, Expression<Func<T, bool>> where) where T : class, new()
        {
            if (item == null) return -9;

            var result = FindBy<T>(where);

            if (result != null) return 1;

            return 0;
        }

        /// <summary>
        /// 检查对象是否在数据库中存在
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where">查询条件表达式</param>
        /// <returns>1 实体对象已经存在；0 不存在（正常情况返回1）</returns>
        public int IsExits<T>(Expression<Func<T, bool>> where) where T : class, new()
        {
            var result = FindBy<T>(where);

            if (result != null) return 1;

            return 0;
        }

        /// <summary>
        /// 删除对象-根据主键
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">主键</param>
        /// <returns></returns>
        public int Delete<T>(int key) where T : class, new()
        {
            return Db.DeleteByKey<T>(key);
        }

        /// <summary>
        /// 删除对象--根据查询表达式
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public int Delete<T>(Expression<Func<T, bool>> where) where T : class, new()
        {
            return Db.Delete<T>(where);
        }

        /// <summary>
        /// 获取页面分页参数
        /// </summary>
        /// <param name="limit"></param>
        /// <param name="offset"></param>
        /// <param name="total"></param>
        /// <returns></returns>
        private static int GetLimit(int limit, ref int offset, int total)
        {
            if (limit > 1000) limit = 100;
            if (limit > total)
            {
                limit = total;
                offset = 0;
            }
            else
            {
                if (offset >= total - limit) offset = total - limit;
            }
            return limit;
        }
    }
}
